#include "usk_logger_impl.h"
#include "usk_logger_impl_private.hpp"

namespace usk {
    namespace core {
        inline std::string GetExceptionMessage(std::exception_ptr const &ex) {
            std::string message = "\nException logged: ";
            if (ex) {
                try {
                    std::rethrow_exception(ex);
                } catch (std::exception const &e) {
                    message += std::string(typeid(e).name()) + " : " + e.what();
                }
            } else {
                message += "none";
            }

            return message;
        }

        inline std::string GetServiceReferenceInfo(ServiceReferenceBase const &sr) {
            std::ostringstream stream;
            stream << "\nServiceReference: " << sr;
            return stream.str();
        }

        USKLoggerImpl::USKLoggerImpl(std::string const &loggerName) {
            d_ = std::make_shared<USKLoggerImplPrivate>(loggerName);
        }

        USKLoggerImpl::USKLoggerImpl(const cppmicroservices::Bundle &bundle,
                                     std::string const &loggerName) {
            const std::string logger_name = bundle.GetSymbolicName() + "." + loggerName;
            d_ = std::make_shared<USKLoggerImplPrivate>(logger_name);
        }

        void USKLoggerImpl::audit(const std::string &message) {
            d_->logger_->trace(message);
        }

        void USKLoggerImpl::audit(std::string const &format, std::string const &arg) {
            d_->logger_->trace(format, arg);
        }

        void USKLoggerImpl::audit(std::string const &format, std::string const &arg1,
                                  std::string const &arg2) {
            d_->logger_->trace(format, arg1, arg2);
        }

        void USKLoggerImpl::audit(std::string const &message,
                                  const std::exception_ptr ex) {
            d_->logger_->trace(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::audit(std::string const &message,
                                  ServiceReferenceBase const &sr) {
            d_->logger_->trace(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::audit(std::string const &message,
                                  ServiceReferenceBase const &sr,
                                  const std::exception_ptr ex) {
            d_->logger_->trace(message + GetServiceReferenceInfo(sr) +
                               GetExceptionMessage(ex));
        }

        void USKLoggerImpl::debug(std::string const &message) {
            d_->logger_->debug(message);
        }

        void USKLoggerImpl::debug(std::string const &format, std::string const &arg) {
            d_->logger_->debug(format, arg);
        }

        void USKLoggerImpl::debug(std::string const &format, std::string const &arg1,
                                  std::string const &arg2) {
            d_->logger_->debug(format, arg1, arg2);
        }

        void USKLoggerImpl::debug(std::string const &message,
                                  const std::exception_ptr ex) {
            d_->logger_->debug(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::debug(std::string const &message,
                                  ServiceReferenceBase const &sr) {
            d_->logger_->debug(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::debug(std::string const &message,
                                  ServiceReferenceBase const &sr,
                                  const std::exception_ptr ex) {
            d_->logger_->debug(message + GetServiceReferenceInfo(sr) +
                               GetExceptionMessage(ex));
        }

        void USKLoggerImpl::error(std::string const &message) {
            d_->logger_->error(message);
        }

        void USKLoggerImpl::error(std::string const &format, std::string const &arg) {
            d_->logger_->error(format, arg);
        }

        void USKLoggerImpl::error(std::string const &format, std::string const &arg1,
                                  std::string const &arg2) {
            d_->logger_->error(format, arg1, arg2);
        }

        void USKLoggerImpl::error(std::string const &message,
                                  const std::exception_ptr ex) {
            d_->logger_->error(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::error(std::string const &message,
                                  ServiceReferenceBase const &sr) {
            d_->logger_->error(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::error(std::string const &message,
                                  ServiceReferenceBase const &sr,
                                  const std::exception_ptr ex) {
            d_->logger_->error(message + GetServiceReferenceInfo(sr) +
                               GetExceptionMessage(ex));
        }

        void USKLoggerImpl::info(std::string const &message) {
            d_->logger_->information(message);
        }

        void USKLoggerImpl::info(std::string const &format, std::string const &arg) {
            d_->logger_->information(format, arg);
        }

        void USKLoggerImpl::info(std::string const &format, std::string const &arg1,
                                 std::string const &arg2) {
            d_->logger_->information(format, arg1, arg2);
        }

        void USKLoggerImpl::info(std::string const &message,
                                 const std::exception_ptr ex) {
            d_->logger_->information(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::info(std::string const &message,
                                 ServiceReferenceBase const &sr) {
            d_->logger_->information(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::info(std::string const &message,
                                 ServiceReferenceBase const &sr,
                                 const std::exception_ptr ex) {
            d_->logger_->information(message + GetServiceReferenceInfo(sr) +
                                     GetExceptionMessage(ex));
        }

        void USKLoggerImpl::trace(std::string const &message) {
            d_->logger_->trace(message);
        }

        void USKLoggerImpl::trace(std::string const &format, std::string const &arg) {
            d_->logger_->trace(format, arg);
        }

        void USKLoggerImpl::trace(std::string const &format, std::string const &arg1,
                                  std::string const &arg2) {
            d_->logger_->trace(format, arg1, arg2);
        }

        void USKLoggerImpl::trace(std::string const &message,
                                  const std::exception_ptr ex) {
            d_->logger_->trace(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::trace(std::string const &message,
                                  ServiceReferenceBase const &sr) {
            d_->logger_->trace(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::trace(std::string const &message,
                                  ServiceReferenceBase const &sr,
                                  const std::exception_ptr ex) {
            d_->logger_->trace(message + GetServiceReferenceInfo(sr) +
                               GetExceptionMessage(ex));
        }

        void USKLoggerImpl::warn(std::string const &message) {
            d_->logger_->warning(message);
        }

        void USKLoggerImpl::warn(std::string const &format, std::string const &arg) {
            d_->logger_->warning(format, arg);
        }

        void USKLoggerImpl::warn(std::string const &format, std::string const &arg1,
                                 std::string const &arg2) {
            d_->logger_->warning(format, arg1, arg2);
        }

        void USKLoggerImpl::warn(std::string const &message,
                                 const std::exception_ptr ex) {
            d_->logger_->warning(message + GetExceptionMessage(ex));
        }

        void USKLoggerImpl::warn(std::string const &message,
                                 ServiceReferenceBase const &sr) {
            d_->logger_->warning(message + GetServiceReferenceInfo(sr));
        }

        void USKLoggerImpl::warn(std::string const &message,
                                 ServiceReferenceBase const &sr,
                                 const std::exception_ptr ex) {
            d_->logger_->warning(message + GetServiceReferenceInfo(sr) +
                                 GetExceptionMessage(ex));
        }
    } // namespace core
} // namespace usk
